﻿using System.Security.Cryptography;
using System.Text;

namespace Easy.Common.Helper
{
    /// <summary>
    /// RSAHelper
    /// </summary>
    public partial class RSAHelper
    {
        private static readonly string privateKey = @"<RSAKeyValue><Modulus>xJPtm+kkmbVqUvDGpYCsQYWvmA86LfC4c7nP/tqfu8vdDWlHV8jUBDR0vWoVrzaelnnQIY1MlIb1+lwcwMOGxRuk7jp78CN0OotZXhQ4esGv5SIWvu2xd4mewY4GBWqBsq5LX9P9/E9flbrEX1d4ZeuYSeIZMa4xwADJT59V5CU=</Modulus><Exponent>AQAB</Exponent><P>8krDbna/awzL2OP5u5nKLYaGVj0WeAanrpnN//kHrpNru9XVzNxTNNfuA0tO8cSm2lswHBzMlz0Y14acH96FZw==</P><Q>z7MQLKjdEhJdr2z08nv+WLI6pcl79SwBc/GUMuwA2a7SshFtbTmICQWrHybwikx+nVbikJQnGLcXfcc3c+4mkw==</Q><DP>Bd7x5VdTRBDHT7YWcwlC8N91mdlZFgdzQLPRXgZ2vTAtSBviVlhwW7NvvPyyKQGO2XOkMsov2upME8zbM5p8uQ==</DP><DQ>WWCq8yzvhRlWK2lttvNYrn5z8mfT6ds3/NbWeVtJumMa0/nf5wK84XUJAGzXUgw86CQ9dw3qDR6tAzk5SbAP9Q==</DQ><InverseQ>zUmu6FT/xl4IV7F7nPt3qceqJh97VOHJ40wVqpDpKR8lNa3WTm9mPsW6n+sA72CFfsGDi6uxrloR8uElnfl+xw==</InverseQ><D>f5MRTXHNEwQtcI5aHOaY5B0CjEi1lUL4MgKQ/fCcYaA4YY/FgS8QiXoRmSvTztY/raB4do3g+TNtR4GoF2HNf9IbJKfvn0n/Qv8Y5lL+iXUWKRuau4bYxNMYO3ZEvlmGnMd9MSKhB3T5Sxj/kzUsmSOecI30jOcGxMqhZSuHbjE=</D></RSAKeyValue>";

        private static readonly string publicKey = @"<RSAKeyValue><Modulus>xJPtm+kkmbVqUvDGpYCsQYWvmA86LfC4c7nP/tqfu8vdDWlHV8jUBDR0vWoVrzaelnnQIY1MlIb1+lwcwMOGxRuk7jp78CN0OotZXhQ4esGv5SIWvu2xd4mewY4GBWqBsq5LX9P9/E9flbrEX1d4ZeuYSeIZMa4xwADJT59V5CU=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

        /// <summary>
        /// Encrypt
        /// </summary>
        /// <param name="str">str</param>
        /// <returns>result</returns>
        public static string Encrypt(string str)
        {
            try
            {
                RSACryptoServiceProvider rsaCSP = new RSACryptoServiceProvider();
                rsaCSP.FromXmlString(publicKey);
                //分段加密,解决加密长度限制问题
                var bufferSize = (rsaCSP.KeySize / 8 - 11);
                byte[] buffer = new byte[bufferSize];//待加密块
                byte[] bytes = Encoding.UTF8.GetBytes(str);
                using (MemoryStream msInput = new MemoryStream(bytes))
                {
                    using (MemoryStream msOutput = new MemoryStream())
                    {
                        int readLen;
                        while ((readLen = msInput.Read(buffer, 0, bufferSize)) > 0)
                        {
                            byte[] dataToEnc = new byte[readLen];
                            Array.Copy(buffer, 0, dataToEnc, 0, readLen);
                            byte[] encData = rsaCSP.Encrypt(dataToEnc, false);
                            msOutput.Write(encData, 0, encData.Length);
                        }
                        byte[] resultBytes = msOutput.ToArray();
                        rsaCSP.Clear();
                        return Convert.ToBase64String(resultBytes);
                    }
                }
            }
            catch (ArgumentException)
            {
                throw new ArgumentNullException("加密字符串不能为空");
            }
            catch (CryptographicException)
            {
                throw new ArithmeticException("加密错误");
            }
        }

        /// <summary>
        /// Decrypt
        /// </summary>
        /// <param name="str">str</param>
        /// <returns>result</returns>
        public static string Decrypt(string str)
        {
            try
            {
                RSACryptoServiceProvider rsaCSP = new RSACryptoServiceProvider();
                rsaCSP.FromXmlString(privateKey);
                byte[] cipherbytes = Convert.FromBase64String(str);
                int keySize = rsaCSP.KeySize / 8;
                byte[] buffer = new byte[keySize];
                using (MemoryStream msInput = new(cipherbytes))
                {
                    using (MemoryStream msOutput = new())
                    {
                        int readLen;

                        while ((readLen = msInput.Read(buffer, 0, keySize)) > 0)
                        {
                            byte[] dataToDec = new byte[readLen];
                            Array.Copy(buffer, 0, dataToDec, 0, readLen);
                            byte[] decData = rsaCSP.Decrypt(dataToDec, false);
                            msOutput.Write(decData, 0, decData.Length);
                        }

                        byte[] resultBytes = msOutput.ToArray();
                        rsaCSP.Clear();
                        return Encoding.UTF8.GetString(resultBytes);
                    }
                }
            }
            catch (ArgumentException)
            {
                throw new ArgumentNullException("解密字符串不能为空");
            }
            catch (FormatException)
            {
                throw new ArithmeticException("解密字符串格式不正确");
            }
            catch (CryptographicException)
            {
                throw new ArithmeticException("解密错误");
            }
        }
    }
}
